/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { TypeNode, SyntaxKind, TypeReferenceNode } from 'ts-morph';
import { PropertyKind, TypeStructure, SerializerMetadata } from '../Types';
import { ITypeHandler, TypeContext, ConversionDirection } from './ITypeHandler';
import { BaseTypeHandler } from './BaseTypeHandler';

export class GenericHandler extends BaseTypeHandler implements ITypeHandler {
  readonly name = 'GenericHandler';
  readonly kind = PropertyKind.GENERIC;
  readonly priority = 95; // 高优先级，在CustomClassHandler之前

  // ==================== 阶段1: 类型识别 ====================

  matches(typeNode: TypeNode, context: TypeContext): boolean {
    // 必须是TypeReference且不能有泛型参数
    if (typeNode.getKind() !== SyntaxKind.TypeReference) {
      return false;
    }

    const typeRef = typeNode as TypeReferenceNode;
    const typeName = typeRef.getTypeName().getText();

    // 没有泛型参数（如果有泛型参数说明是泛型类，不是泛型参数）
    if (typeRef.getTypeArguments().length > 0) {
      return false;
    }

    return context.genericParams.includes(typeName);
  }

  // ==================== 阶段2: 类型解析 ====================

  parse(typeNode: TypeNode): TypeStructure {
    const typeRef = typeNode as TypeReferenceNode;
    const typeName = typeRef.getTypeName().getText();

    return {
      kind: this.kind,
      depth: 0,
      sourceText: typeName,
      args: [],
      dependencies: []
    };
  }

  // ==================== 阶段3: 序列化器配置 ====================

  getSerializerMetadata(structure: TypeStructure, withParam?: string): SerializerMetadata {
    const defaultInstantiation = this.generateInstantiation(structure);

    return {
      name: 'Serializer',
      typeDeclaration: this.generateTypeDeclaration(structure),
      instantiationTemplate: this.applyWithParam(withParam, defaultInstantiation, structure),
      encodeMethod: 'encodeSerializableElement',
      decodeMethod: 'deserialize',
      decoderType: `${structure.sourceText} | undefined`,
      needsTypeAssertion: false
    };
  }

  // ==================== 阶段4: 代码生成 ====================

  generateInstantiation(structure: TypeStructure): string {
    const typeName = structure.sourceText;
    const lowerName = typeName.toLowerCase();
    return `${lowerName}Serializer`; // 如 tSerializer
  }

  generateTypeDeclaration(structure: TypeStructure): string {
    const typeName = structure.sourceText;
    return `Serializer<${typeName}>`;
  }

  generateTypeKey(structure: TypeStructure): string {
    const typeName = structure.sourceText;
    return `'${typeName}'`; // 泛型参数的typeKey就是参数名
  }

  // ==================== Sendable转换 ====================

  generateSendableTypeDeclaration(structure: TypeStructure): string {
    // 泛型参数类型保持不变（泛型参数本身没有Sendable/非Sendable之分）
    return structure.sourceText;
  }

  generatePropertyConversion(structure: TypeStructure, sourceValue: string, direction: ConversionDirection): string {

    if (direction === ConversionDirection.TO_SENDABLE) {
      return `((): ${structure.sourceText}${structure.isOptional ? ' | undefined' : ''} => {
                const sendable: ESObject = ${sourceValue};
                if (sendable.toSendable) {
                  return sendable.toSendable();
                } else {
                  return ${sourceValue}${structure.isOptional ? '' : '!'};
                }
              })()`;
    } else {
      return `((): ${structure.sourceText}${structure.isOptional ? ' | undefined' : ''} => {
                const origin: ESObject = ${sourceValue};
                if (origin.toOrigin) {
                  return origin.toOrigin();
                } else {
                  return ${sourceValue}${structure.isOptional ? '' : '!'};
                }
              })()`;
    }
  }
}

/**
 * 工厂函数
 */
export function createGenericHandler(): ITypeHandler {
  return new GenericHandler();
}
